home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / simula / books / books.lha / kirkerud / dfweather.sim < prev    next >
Text File  |  1993-08-16  |  11KB  |  322 lines

  1. % ****************************************************************
  2. % *                                                              *
  3. % *  This is the program constructed in section 12.9 of          *
  4. % *  Object Oriented Programming with Simula by Bj|rn Kirkerud;  *
  5. % *                                                              *
  6. % ****************************************************************
  7.  
  8. begin
  9.  
  10.   class Place_day(year, month, day, place_number);
  11.       integer year, month, day, place_number;
  12.   begin
  13.  
  14.   ! Declarations of data attributes:  ;
  15.  
  16.     real rain, min_temp, max_temp;
  17.     Boolean sunny;
  18.  
  19.   ! A variable that says whether or not data has been entered
  20.   ! for this Place_day:   ;
  21.  
  22.     Boolean no_data;
  23.  
  24.   ! Declarations of procedures for accessing the data of this Place_day:  ;
  25.  
  26.     procedure Enter_data;
  27.       begin
  28.         rain     := prompt_for_real("Rain (in mm)> ");
  29.         min_temp := prompt_for_real("Min temp.> ");
  30.         max_temp := prompt_for_real("Max temp.> ");
  31.         sunny    := prompt_for_bool("Sunny? ");
  32.         no_data  := false;
  33.       end;
  34.  
  35.     procedure Display_data;
  36.       if not no_data then
  37.         begin
  38.           outtext("Meth. data for " &  date_name(year, month, day) &
  39.                   " at place " & int_as_text(place_number) &  ": "); outimage;
  40.           outtext("   Rain: ");       outfix(rain, 1, 0);      outimage;
  41.           outtext("   Min temp: ");   outfix(min_temp, 1, 0);    outimage;
  42.           outtext("   Max temp: ");   outfix(max_temp, 1, 0);    outimage;
  43.           outtext("   It was " &  (if sunny then notext else "not ") &  
  44.                   "sunny."); outimage;
  45.         end;
  46.  
  47.     procedure Change_data;
  48.       if not no_data then
  49.         begin
  50.           ! Let the user change the values of some data  attributes ;
  51.           User_message("Change data is not implemented.");
  52.         end;
  53.  
  54.     procedure Write_to_file(weather_file);  ref(directfile) weather_file;
  55.       if not no_data then
  56.         begin
  57.           weather_file.outfix(rain, 1, 10);
  58.           weather_file.outfix(min_temp, 1, 10);
  59.           weather_file.outfix(max_temp, 1, 10);
  60.           weather_file.outint(if sunny then 1 else 0, 2);
  61.           weather_file.locate(location_number(year, month, day, place_number));
  62.           weather_file.outimage;
  63.         end of Write_to_file;
  64.  
  65.     procedure Read_from_file(weather_file);  ref(directfile) weather_file;
  66.       begin
  67.         weather_file.locate(location_number( year, month, day, place_number));
  68.         weather_file.inimage;
  69.         if image_is_empty(weather_file)
  70.           then no_data := true
  71.           else begin
  72.               rain     := weather_file.inreal;
  73.               min_temp := weather_file.inreal;
  74.               max_temp := weather_file.inreal;
  75.               sunny    := weather_file.inint = 1;
  76.               no_data  := false;
  77.             end;
  78.       end of Read_from_file;
  79.  
  80.   ! Initialization:   ;
  81.  
  82.     no_data := true;
  83.  
  84.   end of Place_day;
  85.  
  86.  
  87. ! A variable to keep a reference to the direct file where
  88. ! data about all Place_days are kept:   ;
  89.  
  90.   ref(directfile) weather_file;
  91.  
  92. ! A procedure that calculates where in the direct file to
  93. ! put data about a Place_day:   ;
  94.  
  95.   integer procedure location_number( year, month, day, place_number);
  96.       integer year, month, day, place_number;
  97.     location_number :=  (place_number - 1)*100*366
  98.                 + year*366
  99.                 + month_start(month)
  100.                 + day;
  101.  
  102.  
  103. ! Procedures to handle the actions the program is able to  execute:    ;
  104.  
  105.   procedure Enter_place_day;
  106.     begin
  107.       integer year, month, day, place_number;
  108.       ref(Place_day) a_place_day;
  109.       prompt_for_date(year, month, day);
  110.       place_number := prompt_for_int("Place-number? ");
  111.       weather_file.locate( location_number(year, month, day, place_number));
  112.       weather_file.inimage;
  113.       if not image_is_empty(weather_file)
  114.         then User_message("You have entered data for this place-day "
  115.                   "previously!")
  116.         else begin
  117.           a_place_day :- new Place_day(year, month, day,  place_number);
  118.           a_place_day.Enter_data;
  119.           a_place_day.Write_to_file(weather_file);
  120.         end;
  121.     end of Enter_place_day;
  122.  
  123.   procedure Display_place_day;
  124.     begin
  125.       integer year, month, day, place_number;
  126.       ref(Place_day) a_place_day;
  127.       prompt_for_date(year, month, day);
  128.       place_number := prompt_for_int("Number of place? ");
  129.       a_place_day :- new Place_day(year, month, day,  place_number);
  130.       a_place_day.Read_from_file(weather_file);
  131.       if a_place_day.no_data
  132.         then User_message( "No data known for this place-day!")
  133.         else a_place_day.Display_data;
  134.     end of Display_place_day;
  135.  
  136.   procedure Change_place_day;
  137.     begin
  138.       integer year, month, day, place_number;
  139.       ref(Place_day) a_place_day;
  140.       prompt_for_date(year, month, day);
  141.       place_number := prompt_for_int("Number of place? ");
  142.       a_place_day :- new Place_day(year, month, day,  place_number);
  143.       a_place_day.Read_from_file(weather_file);
  144.       if a_place_day.no_data
  145.         then User_message( "No data known for this place-day!")
  146.         else begin
  147.             a_place_day.Display_data;
  148.             a_place_day.Change_data;
  149.             a_place_day.Write_to_file(weather_file);
  150.           end;
  151.     end of Change_place_day;
  152.  
  153.   procedure Statistics;
  154.     begin
  155.       User_message("Statistics is not implemented");
  156.     end of Statistics;
  157.  
  158.  
  159.   procedure Give_help;
  160.     begin
  161.       User_message("The legal commands are: ");
  162.       User_message("   ?:  Help (writes this text)");
  163.       User_message("   E:  To enter data about a single place-day");
  164.       User_message("   D:  Writes data about a single place-day");
  165.       User_message("   C:  To change data about a single place-day");
  166.       User_message("   S:  Produces some statistics");
  167.       User_message("   Q:  Quit (the program execution stops)");
  168.     end of Give_help;
  169.  
  170.  
  171.   procedure Read_and_execute_commands;
  172.     begin character command;
  173.       command := prompt_for_char("Type your first command  (? for help) > ");
  174.       while command ne  'Q' do
  175.         begin
  176.           if command = '?' then Give_help         else
  177.           if command = 'E' then Enter_place_day   else
  178.           if command = 'D' then Display_place_day else
  179.           if command = 'C' then Change_place_day  else
  180.           if command = 'S' then Statistics
  181.           else begin 
  182.               outtext("Unknown command: "); outchar(command); outimage;
  183.             end;
  184.           command := prompt_for_char("Your next command > ");
  185.         end;
  186.     end of Read_and_execute_commands;
  187.  
  188.  
  189. !  Declarations of some auxiliary procedures:    ;
  190.  
  191.   text procedure int_as_text(int); integer int;
  192.     begin text t; integer a;
  193.       a := abs(int);
  194.       t :- blanks((if int < 0 then 1 else 0) +
  195.                   (if a < 10 then 1 else
  196.                    if a < 100 then 2 else
  197.                    if a < 1000 then 3 else
  198.                    if a < 10000 then 4 else
  199.                    if a < 100000 then 5 else
  200.                    if a < 1000000 then 6 else
  201.                    if a < 10000000 then 7 else
  202.                    if a < 100000000 then 8 else
  203.                    if a < 1000000000 then 9 else 10));
  204.       t.putint(int);
  205.       int_as_text :- t;
  206.     end;
  207.  
  208.   procedure User_message(message); text message;
  209.     begin outtext(message); outimage end;
  210.  
  211.   integer procedure prompt_for_int(prompt); text prompt;
  212.     begin
  213.       outtext(prompt); breakoutimage; inimage;
  214.       prompt_for_int := inint;
  215.     end;
  216.  
  217.   character procedure prompt_for_char(prompt); text prompt;
  218.     begin
  219.       outtext(prompt); breakoutimage; inimage;
  220.       prompt_for_char := inchar;
  221.     end;
  222.  
  223.   real procedure prompt_for_real(prompt); text prompt;
  224.     begin
  225.       outtext(prompt); breakoutimage; inimage;
  226.       prompt_for_real := inreal;
  227.     end;
  228.  
  229.   Boolean procedure prompt_for_bool(prompt); text prompt;
  230.     begin character c;
  231.       outtext(prompt); breakoutimage; inimage;
  232.       c := inchar;
  233.       prompt_for_bool := c = 'y' or c = 'Y';
  234.     end;
  235.  
  236.   procedure prompt_for_date(year, month, day);
  237.       name year, month, day; integer year, month, day;
  238.     begin
  239.       year  := prompt_for_int("Year? ");
  240.       month := prompt_for_int("Month? ");
  241.       day   := prompt_for_int("Day? ");
  242.       if not legal_date(year, month, day) then
  243.         begin
  244.           User_message("Illegal date! Try again!");
  245.           prompt_for_date(year, month, day);
  246.         end;
  247.     end;
  248.  
  249.   Boolean procedure legal_date(year, month, day);
  250.       integer year, month, day;
  251.     legal_date := 1 <= month and month <= 12 and then
  252.                   1 <= day and day <= 31 and then
  253.            not (day = 31 and  
  254.                 (month = 4 or month = 6 or  month = 9 or month = 11)) and then
  255.            not (month = 2 and day > 29) and then
  256.            not (month = 2 and day = 29 and  rem(year, 4) > 0);
  257.  
  258.   text procedure date_name(year, month, day);  integer year, month, day;
  259.     if not legal_date(year, month, day)
  260.       then date_name :- notext
  261.       else begin text t;
  262.           t :- blanks(11);
  263.           t.sub(1, 2).putint(day);
  264.           t.sub(3, 1).putchar('.');
  265.           t.sub(4, 3) := month_name(month);
  266.           t.sub(8, 4).putint(year);
  267.           date_name :- t;
  268.       end;
  269.  
  270.   text array month_name(1 : 12);
  271.   integer array month_start(1 : 12);
  272.  
  273.   procedure Initialize_months;
  274.     begin
  275.       month_name( 1) :- "jan"; month_start( 1) :=   1;
  276.       month_name( 2) :- "feb"; month_start( 2) := 31 + month_start( 1);
  277.       month_name( 3) :- "mar"; month_start( 3) := 29 + month_start( 2);
  278.       month_name( 4) :- "apr"; month_start( 4) := 31 + month_start( 3);
  279.       month_name( 5) :- "may"; month_start( 5) := 30 + month_start( 4);
  280.       month_name( 6) :- "jun"; month_start( 6) := 31 + month_start( 5);
  281.       month_name( 7) :- "jul"; month_start( 7) := 30 + month_start( 6);
  282.       month_name( 8) :- "aug"; month_start( 8) := 31 + month_start( 7);
  283.       month_name( 9) :- "sep"; month_start( 9) := 31 + month_start( 8);
  284.       month_name(10) :- "oct"; month_start(10) := 30 + month_start( 9);
  285.       month_name(11) :- "nov"; month_start(11) := 31 + month_start(10);
  286.       month_name(12) :- "dec"; month_start(11) := 30 + month_start(11);
  287.     end Initialize_months;
  288.  
  289.   Boolean procedure image_is_empty(df);  ref(directfile) df;
  290.     image_is_empty :=  df.image.sub(1,1).getchar =  '!0!'  or else
  291.                        df.image.sub(1,1).getchar =  '!31!' or else
  292.                        df.image.sub(1,1).getchar =  '!25!';
  293.  
  294.  
  295. !  That was the end of the declarations.  Now come the imperatives:    ;
  296.  
  297. !  First,  initialize the file:    ;
  298.  
  299.   weather_file :- new directfile("Weather.dta");
  300.   weather_file.setaccess("anycreate");
  301.   if not weather_file.open(blanks(10 + 10 + 10 + 2))
  302.     then User_message("File problems!")
  303.     else begin
  304.  
  305. !     Then, initialize month names and month lengths:   ;
  306.  
  307.       Initialize_months;
  308.  
  309.  
  310. !     Then, read and execute commands typed by the user: ;
  311.  
  312.       Read_and_execute_commands;
  313.  
  314.  
  315. !     Finally, close the file:    ;
  316.  
  317.       weather_file.close;
  318.   
  319.     end;
  320.  
  321. end
  322.